use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;

use enigo::*;

use crate::base::ServerError;
use crate::db::model::operation::{list_operation, Operation, OperationType};

pub async fn start_work(group_id: i32, is_loop: bool) -> Result<(), ServerError> {
    let res = list_operation(group_id).await;
    if let Ok(operations) = res {
        thread::spawn(move || {

            let mut enigo = Enigo::new();
            if (is_loop){
                loop {
                    for Operation { step, params, operation_type, .. } in &operations {
                        let param = &params.0;
                        match operation_type {
                            OperationType::KeyDown => {
                                if let Some(key) = param.key {
                                    tracing::info!("按键:{:?}",key);
                                    enigo.key_down(key.into());
                                    thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                                }
                            }
                            OperationType::KeyUp => {
                                if let Some(key) = param.key {
                                    enigo.key_up(key.into());
                                    thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                                }
                            }
                            OperationType::MouseTo => {
                                match (param.screenX, param.screenY) {
                                    (Some(x), Some(y)) => {
                                        enigo.mouse_move_to(x, y);
                                        thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                                    }
                                    _ => {}
                                }
                            }
                            OperationType::MouseLeftClick => {
                                enigo.mouse_click(MouseButton::Left);
                                thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                            }
                            OperationType::MouseRightClick => {
                                enigo.mouse_click(MouseButton::Right);
                                thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                            }
                            OperationType::DELAY => {
                                thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                            }
                        }
                    }
                }
            }else {
                do_enigo(operations, enigo);

            }
        });
    }
    Ok(())
}

fn do_enigo(operations: Vec<Operation>, mut enigo: Enigo) {
    for Operation { step, params, operation_type, .. } in operations {
        let param = params.0;
        match operation_type {
            OperationType::KeyDown => {
                if let Some(key) = param.key {
                    tracing::info!("按键:{:?}",key);
                    enigo.key_down(key.into());
                    thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                }
            }
            OperationType::KeyUp => {
                if let Some(key) = param.key {
                    enigo.key_up(key.into());
                    thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                }
            }
            OperationType::MouseTo => {
                match (param.screenX, param.screenY) {
                    (Some(x), Some(y)) => {
                        enigo.mouse_move_to(x, y);
                        thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
                    }
                    _ => {}
                }
            }
            OperationType::MouseLeftClick => {
                enigo.mouse_click(MouseButton::Left);
                thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
            }
            OperationType::MouseRightClick => {
                enigo.mouse_click(MouseButton::Right);
                thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
            }
            OperationType::DELAY => {
                thread::sleep(Duration::from_millis(param.time.unwrap_or_else(|| 0) as u64));
            }
        }
    }
}